# -*- coding: utf-8 -*-

import os
import re
import shutil
import codecs
import ConfigParser
from xml.dom import minidom
from optparse import OptionParser

class packapp(object):
    
    def __init__(self): 
        self.__apk_name = ""                    #最终包名称(默认为Imay)
        self.__source_android_path = ""         #源项目android工程路径
        self.__source_app_path = ""             #源项目的manifest配置文件路径
        self.__output_path = ""                 #输出路径
        self.__python_path = os.path.abspath('.')#当前路径
        self.__isNeedSplit = True                #输入参数,打好的包是否需要分离
        self.__channel_id = ""                  #需要打包的渠道ID
        self.__config_path = ""                 #配置文件路径
        self.__channel = ""                     #当前打包的渠道名称
        
        self.__option = None                    #输入参数
                    
    def __replace_text_by_file(self, path, old, new):
        '''替换文本文件中的文本
        '''

        sub, name = os.path.split(path)
        temp_path = os.path.join(sub, "temp_" + name)
        if os.path.isfile(temp_path):
            os.remove(temp_path)
        shutil.copy(path, temp_path)
        
        cur_file = codecs.open(path, "w", "utf-8")
        temp_file = codecs.open(temp_path, "r", "utf-8")
        # print("temp_path",temp_path)
        # print("temp_file",temp_file)
        # print("cur_file",cur_file)
        for line in temp_file.readlines():
            cur_file.write(line.replace(old, new))
        cur_file.close()
        temp_file.close()
        
        os.remove(temp_path)
        
    def __get_config_value(self, key, data):
        '''获取配置信息
        '''
        if data == "":
            data = "data"

        cf = ConfigParser.ConfigParser()
        dst = os.path.join(self.__source_config_path, self.__source_config)
        cf.read(dst)
        value = cf.get(data, key)
        # print("111",cf.get("application", "textdata"))
    
        # print("222",cf.get("manifest", "textdata"))
        return value
    
    def __check_arguments(self):
        '''检查参数
        '''
        
        parser = OptionParser()
        parser.add_option("-p", action="store", type="string", dest="project", help="project path")#母包目录,可自定义,否则默认
        parser.add_option("-o", action="store", type ="string", dest="output", help="output path")#输出目录,可自定义,否则为默认
        parser.add_option("-c", action="store", type="string", dest="channel", help="channel name")#调用脚本时输入的参数,如果输入,则为制定渠道打包,否则为所有渠道打包
        parser.add_option("-n", action="store", type="string", dest="name", help="game name")#包名字,可自定义,否则为默认的
        parser.add_option("-s", action="store", type="string", dest="split", help="need split")#是否需要将打好的包分离,输入"true"是需要分离,"false"为不分离,默认为true
        (options, args) = parser.parse_args()
        
        self.__option = options
        
        ok = True
            
        #更新文件路径
        if ok:
            self.__source_android_path = options.project
            if options.project == None:
                #如果母包路径参数没有写,就设置一个默认值
                self.__source_android_path = os.path.join(self.__python_path, os.pardir, os.pardir, "frameworks", "runtime-src" ,"proj.android-studio")

            self.__output_path = options.output
            if options.output == None:
                #如果输出目录没有写,则在源目录中新建一个output目录作为输出目录
                self.__output_path = os.path.join(self.__python_path, "output")

            self.__channel_id = options.channel
            if options.channel == None:
                #如果输出目录没有写,则在源目录中新建一个output目录作为输出目录
                self.__channel_id = "all"

            self.__apk_name = options.name
            if options.name == None:
                #如果名字参数没有写,就设置一个默认值
                self.__apk_name = "Imay"

            self.__isNeedSplit = options.split == "true"
            if options.split == None:
                #如果是否分离没有输入,设置为默认
                self.__isNeedSplit = True

            self.__config_path = os.path.join(self.__python_path, "config", "all.config")
            self.__source_app_path = os.path.join(self.__source_android_path, "app")

        return True

    def __check_project(self):
        '''检查母项目
        '''
        # print("check arguments",self.__source_path)
        if not os.path.exists(self.__source_android_path):
            return False
        
        return True
        
    def __replace_manifest_by_name(self, name, dest):
        '''根据配置修改数据
        '''
        #AndroidManifest.xml文件路径
        path = os.path.join(self.__source_app_path, "AndroidManifest.xml")
        
        #获取属性
        dom = minidom.parse(path)
        oldValue = ""
        newValue = ""
        old_value = dom.documentElement.getAttribute(name)
        new_value = dest

        if old_value == "":
            # 当xml文件中找不到指定属性时
            itemlist = dom.getElementsByTagName('meta-data')   
            for s in itemlist :  
                newname = s.attributes['android:name'].value  
                value = s.attributes['android:value'].value  
                if newname == name:
                    oldValue = "android:name=" + "\"%s\"" % (newname) + " android:value" + "=\"%s\"" % (value)
                    newValue = "android:name=" + "\"%s\"" % (newname) + " android:value" + "=\"%s\"" % (new_value)
                    break
        else:            #修改AndroidManifest.xml中的包名
            oldValue = name + "=\"%s\"" % (old_value)
            newValue = name + "=\"%s\"" % (new_value)

        # print(oldValue, newValue)
        self.__replace_text_by_file(path, oldValue, newValue)

    def __replace_manifest(self, value):
        '''修改manifest中的数据
        '''
        self.__replace_manifest_by_name("ChannelID", value)

    def __update_androidmanifest(self, value):
        '''更新AndroidManifest.xml
        '''

        self.__replace_manifest(value)
        
        return True
    
    def __pre_release(self):
        '''打包前的操作,根据配置替换icon和jar包
        '''
            
        return True
    
    def __release(self):
        '''生成apk文件
        '''
        
        # #执行ant clean
        # cmd = "ant clean -f " + os.path.join(self.__source_android_path, "app", "build.xml")
        # os.system(cmd)
        
        # #执行ant release
        # cmd = "ant release -f " + os.path.join(self.__source_android_path, "app", "build.xml")
        # os.system(cmd)

        #执行ant release
        cmd = os.path.join(self.__python_path, os.pardir, os.pardir, "build_androidStudio_release.bat")
        os.system(cmd)
        
        #检测是否有输出目录,如果没有,创建一个
        if not os.path.exists(self.__output_path):
            os.makedirs(self.__output_path)
        
        file_name = None
        path = os.path.join(self.__python_path, os.pardir, os.pardir, "publish", "android")
        items = os.listdir(path)
        for item in items:
            if item.find(".apk") > 0:
                file_name = item
                break
        
        if file_name == None:
            return False

        src = os.path.join(path, file_name)
        dst = os.path.join(self.__output_path, file_name)
        if self.__isNeedSplit:#是否需要分离放包
            dstpath = os.path.join(self.__output_path, self.__channel)
            dst = os.path.join(dstpath, file_name)
            if not os.path.exists(dstpath):
                os.makedirs(dstpath)
        if os.path.exists(dst):
            os.remove(dst)
        shutil.move(src, dst)
        tempsrc = dst

        name = os.path.join(self.__output_path, self.__apk_name + self.__channel + ".apk")
        if self.__isNeedSplit:
            name = os.path.join(self.__output_path, self.__channel, self.__apk_name + "_" + self.__channel  + ".apk")

        print("tempsrc = " , tempsrc)
        print("name = " , name)
        os.rename(tempsrc, name )
        
        return True
    def clean_temp(self):
        '''最后移除临时文件夹
        '''
        # shutil.rmtree(self.__temp_path)

    
    def start(self):
        ok = self.__check_arguments()
        if ok:
            print("check arguments success!!!")
        else:
            print("check arguments fail!!!")
            return

        ok = self.__check_project()
        if ok:
            print("check project success!!!")
        else:
            print("check project fail!!!")
            return

        ok = self.loop()
        if ok:
            print("loop success!!!")
        else:
            print("loop fail!!!")
            return
        
        self.clean_temp()
        print("SDK FINISH!!!")
    def loop(self):
        '''循环过程,批量打包
        '''
        cf = ConfigParser.ConfigParser()
        cf.read(self.__config_path)
        opts = cf.options("channel_data")
        for key in opts:
            isCan = False
            self.__channel = key
            #判断当前渠道是否需要打包
            if self.__channel_id == "all":
                isCan = True
            else:
                if key == self.__channel_id:
                    isCan = True

            if isCan:
                value = cf.get("channel_data", key)

                ok = self.__update_androidmanifest(value)
                if ok:
                    print("update AndroidManifest success!!!")
                else:
                    print("update AndroidManifest fail!!!")
                    return False
                
                ok = self.__pre_release()
                if ok:
                    print("pre release success!!!")
                else:
                    print("pre release fail!!!")
                    return False
                
                ok = self.__release()
                if ok:
                    print("release success!!!")
                else:
                    print("release fail!!!")
                    return False

        return True

def main():
    packapp().start()
    
if __name__ == '__main__':
    main()